using System;
using System.Collections.Generic;
using System.Text;
using GarageGames.Torque.T2D;
using GarageGames.Torque.Core;
using GarageGames.Torque.Materials;
using Microsoft.Xna.Framework;
using GarageGames.Torque.Sim;

using Xyne.Templates.PuzzlePieceTemplate;
using Xyne.Utilities;
using Xyne.Events;
using GarageGames.Torque.Lighting;
using Xyne.Templates.PuzzleGlowTemplate;

namespace Xyne.Templates
{
    public class Sweep : T2DStaticSprite, ITickObject
    {
        private static Sweep template = new Sweep();
        // Unload callback delegate
        public delegate void SweepDoneDelegate();
        // Unload callback
        private SweepDoneDelegate onSweepDone = null;
        // Check selection delegate
        public delegate void CheckForSelectionDelegate(PuzzlePiece piece);
        // Check selection callback
        private CheckForSelectionDelegate checkForSelection = null;
        // Tracking variable
        private float trackX = 0;

        public SweepDoneDelegate OnSweepDone
        {
            get { return onSweepDone; }
            set { onSweepDone = value; }
        }

        public CheckForSelectionDelegate CheckForSelection
        {
            get { return checkForSelection; }
            set { checkForSelection = value; }
        }

        public static Sweep Template
        {
            get { return template; }
        }

        public Sweep()
        {
            // Set the template and name
            IsTemplate = true;
            Name = Game.SweepName;

            // Various parameters
            CreateWithWorldLimit = true;
            SimpleMaterial material = new SimpleMaterial();
            material.TextureFilename = @"data\images\ui\puzzleboard\sweep.png";
            Material = material;
            Layer = Game.SweepLayer;
            ObjectType = TorqueObjectDatabase.Instance.GetObjectType(Name);
        }

        public void ResetSweepState()
        {
            Visible = false;
            trackX = WorldLimit.MoveLimitMin.X + (Game.PuzzlePieceWidth / 2);
            WarpToPosition(new Vector2(WorldLimit.MoveLimitMin.X - (Size.X / 2), WorldLimit.MoveLimitMin.Y + (Size.Y / 2)), 0);
            Physics.VelocityX = 0;
        }

        public void StartSweep()
        {
            Visible = true;
            Physics.VelocityX = 200;

            if (Game.Network != null && Game.Network.Gamer != null)
            {
                StartCastingEvent e = new StartCastingEvent(this);
                e.Gamer = Game.Network.Gamer.Gamertag;
                Game.Network.HandleEvent(e);
            }
        }

        public void StopSweep()
        {
            List<T2DStaticSprite> staticSprites = TorqueObjectDatabase.Instance.FindRegisteredObjects<T2DStaticSprite>();
            foreach (T2DStaticSprite sprite in staticSprites)
            {
                if (sprite.Name == Game.PuzzleGlowName)
                    sprite.MarkForDelete = true;
            }
            List<T2DAnimatedSprite> animatedSprites = TorqueObjectDatabase.Instance.FindRegisteredObjects<T2DAnimatedSprite>();
            foreach (T2DAnimatedSprite sprite in animatedSprites)
            {
                if (sprite.Name == Game.PuzzlePulseName)
                    sprite.MarkForDelete = true;
            }

            Visible = false;
            Physics.VelocityX = 0;

            if (Game.Network != null && Game.Network.Gamer != null)
            {
                StopCastingEvent e = new StopCastingEvent(this);
                e.Gamer = Game.Network.Gamer.Gamertag;
                Game.Network.HandleEvent(e);
            }
        }

        public override void CopyTo(TorqueObject obj)
        {
            base.CopyTo(obj);

            ProcessList.Instance.AddTickCallback(obj, (ITickObject)obj, 0);
        }

        public override void ProcessTick(Move move, float dt)
        {
            // quick and dirty, needs a little refinement
            if (WorldLimit.MoveLimitMax.X < Position.X)
            {
                StopSweep();

                if (onSweepDone != null)
                    onSweepDone();
            }
            else
            {
                if (checkForSelection != null && Visible && Position.X + (Size.X / 2) >= trackX)
                {
                    List<PuzzlePiece> pieces = new List<PuzzlePiece>();
                    TorqueObjectDatabase.Instance.FindRegisteredObjects<PuzzlePiece>(ref pieces);

                    foreach (PuzzlePiece piece in pieces)
                    {
                        if ((int)Math.Round(piece.Position.X) == trackX && piece.Selectable && piece.MountedTo == null)
                        {
                            checkForSelection(piece);
                        }
                    }

                    trackX += Game.PuzzlePieceWidth;
                }
            }
        }

        public override void InterpolateTick(float k)
        {
        }

        private void OnWorldCollision(T2DSceneObject ourObject, T2DSceneObject theirObject, ref T2DCollisionInfo info,
            T2DCollisionMaterial physicsMaterial, bool handleBoth)
        {
            if (info.Normal.X < 0)
            {
                StopSweep();

                if (onSweepDone != null)
                    onSweepDone();
            }
        }
    }
}
